package com.asialjim.wechat.spring.database.impl;

import com.asialjim.wechat.database.CRUD_DataBaseService;
import com.asialjim.wechat.database.DataBaseService;
import com.asialjim.wechat.database.DataBaseTableInfo;
import com.asialjim.wechat.utils.JsonUtils;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;

/**
 * <h1><em>ASIAL JIM JAVA DOC</em></h1><hr/>
 * <h2>CLASS DESCRIPTION <i>[ NAME: CRUD_DataBaseServiceImpl ]</i></h2><strong>
 * <p> CRUD data base service
 * </strong><p><p><em>Copyright &copy; Asial Jim Co., LTD</em><hr/>
 *
 * @author Asial Jim &nbsp;&nbsp; <span>Email:<a href="mailto:asialjim@hotmail.com">asialjim@hotmail.com</a> &nbsp;&nbsp; <a href="asialjim@qq.com">asialjim@qq.com</a></span>
 * @version 1.0.0
 * @since 2021/3/17   &nbsp;&nbsp; JDK 8
 */
@Slf4j
//@Component(CRUD_DataBaseService.BEAN_NAME)
@Component
@AllArgsConstructor
public class CRUD_DataBaseServiceImpl implements CRUD_DataBaseService {
    private final DataBaseService dataBaseService;

    @Override
    public int add2Table(String tableName, List<DataBaseTableInfo> conditions) {
        log.info("\r\n\tadd record: [{}] to table: [{}]",conditions,tableName);
        try {
            Object o = recordByTableName(tableName, conditions);
            int insert = dataBaseService.insert(o);
            log.info("\r\n\tadd record: [{}] to table: [{}] result: [{}]", o, tableName, insert);
            return insert;
        }catch (Exception e){
            return -1;
        }
    }

    @Override
    public int deleteRecord(String tableName, List<DataBaseTableInfo> conditions) {
        log.info("\r\n\tdelete record: [{}] to table: [{}]",conditions,tableName);

        try {
            Object o = recordByTableName(tableName, conditions);
            int delete = dataBaseService.delete(o);
            log.info("\r\n\tdelete record: [{}] from table: [{}] result: [{}]", o, tableName, delete);
            return delete;
        } catch (Exception e){
            return -1;
        }
    }

    @Override
    public int updateRecord(String tableName, List<DataBaseTableInfo> conditions, List<DataBaseTableInfo> source) {
        log.info("\r\n\tupdate table: [{}] to: [{}} where condition equals: [{}}]",tableName,source,conditions);
        try {
            Object condition = recordByTableName(tableName, conditions);
            Object sourceObject = recordByTableName(tableName, source);
            int update = dataBaseService.update(sourceObject, condition);
            log.info("\r\n\tupdate table: [{}] to: [{}} where condition equals: [{}}], result: [{}]",tableName,source,conditions,update);
            return  update;
        } catch (Exception e){
            return -1;
        }
    }

    @Override
    public IPage<Object> selectPage(String tableName, Integer pageNum,Integer pageSize, List<DataBaseTableInfo> conditions) {
        try {
            Object o = recordByTableName(tableName, conditions);
            Page<Object> page = new Page<>();
            page.setSize(pageSize);
            page.setCurrent(pageNum);
            return dataBaseService.selectPage(page, o);
        } catch (Exception e){
            return null;
        }
    }

    @Override
    public List<Object> all(String tableName) throws Exception {
        Class<?> aClass = dataBaseService.classByTableName(tableName);
        if (Objects.isNull(aClass)){
            log.warn("\r\n\tthere is no table class for table name :[{}]",tableName);
            throw new IllegalStateException("there is no table class for table name: " + tableName);
        }
        Object o = aClass.newInstance();
        List<Object> objects = dataBaseService.selectList(o);
        log.info("\r\n\tquery all record for table: [{}]",tableName);
        return objects;
    }

    private Object recordByTableName(String tableName, List<DataBaseTableInfo> conditions) {
        if (Objects.isNull(conditions) || conditions.parallelStream().map(DataBaseTableInfo::getValue).allMatch(Objects::isNull)){
            log.warn("\r\n\tALL TABLE OPERATION FORBID!!!");
            throw new IllegalArgumentException("ALL TABLE OPERATION FORBID!!!!");
        }

        Class<?> aClass = dataBaseService.classByTableName(tableName);
        if (Objects.isNull(aClass)){
            log.warn("\r\n\tthere is no table class for table name :[{}]",tableName);
            throw new IllegalStateException("there is no table class for table name: " + tableName);
        }

        var map = new HashMap<String, Object>();
        conditions.forEach(info -> map.put(info.getPropertyName(),info.getValue()));
        Object o = JsonUtils.toObject(map, aClass);
        log.info("\r\n\tparse record: [{}] to JAVA object: [{}]",conditions,o);
        return o;
    }
}
